package pay

import (
	"context"
	"crypto/sha256"
	"video-api/internal/dao"
	"video-api/internal/model/entity"
	"video-api/internal/model/input"
	"video-api/internal/model/out"
	"video-api/internal/service"

	"github.com/gogf/gf/errors/gerror"
	"github.com/gogf/gf/v2/util/gconv"
)

// 客户端拉起 Google Pay 并创建订单：
// 客户端集成 Google Pay SDK，用户选择 Google Pay 支付方式。
// Google Pay 返回一个支付令牌（Payment Token），其中包含用户的支付信息（如卡号或虚拟账户）。
// 客户端将支付令牌发送给服务器：
// 客户端将 Google Pay 返回的支付令牌传递到商家的服务器。
// 服务器负责处理这个支付令牌，与支付网关进行交互。
// 服务器请求支付网关接口：
// 服务器将支付令牌和订单信息发送到支付网关（如钱海）进行验证和支付处理。
// 此时，支付网关可能会拉起其自己的支付页面（如果需要进一步的用户交互，如信用卡信息补充）。
// 用户填写支付网关的支付信息：
// 如果支付网关需要额外的信息（如信用卡号、CVV 等），用户在支付网关页面完成输入。
// 支付网关请求银行系统进行支付：
// 支付网关将用户的支付信息转发给发卡行或其他支付清算机构进行验证和资金扣除。
// 支付网关返回支付结果给商家服务器：
// 支付网关收到银行的处理结果后，将结果通知商家服务器（同步或异步）。
// Google Pay 接收支付结果（可选）：
// 如果 Google Pay 需要记录支付成功与否（例如为了更新其交易记录或保护用户隐私），支付网关可能会通知 Google Pay。
// 通常情况下，这一步是由支付网关实现的，商家不需要直接参与。
// 服务器返回支付结果给客户端：
// 商家服务器将支付网关的结果返回给客户端，告知用户支付是否成功。
type oOceanPayment struct{}

type OceanPaymentSignatureParams struct {
	Account          string
	Terminal         string
	backUrl          string
	OrderNumber      string
	OrderCurrency    string
	OrderAmount      string // fmt.Sprintf("%.2f", num)
	BillingFirstName string
	BillingLastName  string
	BillingEmail     string
	SecureCode       string
}

// OceanPaymentApiParams TODO 钱海支付参数，应该没有这么多，具体届时看文档修改
type OceanPaymentApiParams struct {
	Account          string
	Terminal         string
	OrderNumber      string
	OrderCurrency    string
	OrderAmount      string // fmt.Sprintf("%.2f", num)
	backUrl          string
	NoticeUrl        string
	SignValue        string
	OrderNotes       string
	Method           string
	BillingFirstName string
	BillingLastName  string
	BillingEmail     string
	BillingPhone     string
	BillingCountry   string
	BillingState     string
	BillingCity      string
	BillingAddress   string
	BillingZip       string
	ProductName      string
	ProductNum       string
	ProductSku       string
	ShipFirstName    string
	ShipLastName     string
	ShipPhone        string
	ShipCountry      string
	ShipState        string
	ShipCity         string
	ShipAddr         string
	ShipZip          string
	ShipEmail        string
	CartInfo         string
	CartApi          string
	Pages            string
}

func init() {
	service.RegisterOceanPayService(&oOceanPayment{})
}

func (o *oOceanPayment) OrderPay(ctx context.Context, params *input.OrderPay) (orderInfo *out.OrderEntity, err error) {
	oModel := dao.Orders.Ctx(ctx)
	orders := new(entity.Orders)
	err = oModel.Where("id = ?", params.OrderId).Scan(orders)
	if err != nil {
		return nil, err
	}
	orderInfo = new(out.OrderEntity)
	err = gconv.Structs(orders, orderInfo)
	if err != nil {
		return nil, err
	}
	//获取签名
	signParams := OceanPaymentSignatureParams{
		Account:          "123",
		Terminal:         "123",
		backUrl:          "123",
		OrderNumber:      "123",
		OrderCurrency:    "123",
		OrderAmount:      "123",
		BillingFirstName: "123",
		BillingLastName:  "123",
		BillingEmail:     "123",
		SecureCode:       "123",
	}
	signature, err := o.GenerateSignature(ctx, signParams)
	if err != nil {
		return nil, err
	}
	// TODO 生成钱海平台order num...
	// TODO 签名加入请求参数，发起支付
	var apiParams = &OceanPaymentApiParams{
		Account:   "oceanpayment account",
		Terminal:  "oceanpayment terminal",
		SignValue: signature,
	}
	err = o.RequestApiToPay(ctx, apiParams)
	if err != nil {
		return nil, gerror.New("order pay err for oceanpayment api.")
	}
	return orderInfo, nil
}

// RequestApiToPay TODO 发起钱海支付
func (o *oOceanPayment) RequestApiToPay(ctx context.Context, params any) error {
	return nil
}

func (o *oOceanPayment) GenerateSignature(ctx context.Context, params any) (string, error) {
	if p, ok := params.(OceanPaymentSignatureParams); ok {
		signTmp := p.Account + p.Terminal + p.backUrl + p.OrderNumber + p.OrderCurrency + p.OrderAmount + p.BillingFirstName + p.BillingLastName + p.BillingEmail + p.SecureCode
		hash := sha256.New()
		hash.Write([]byte(signTmp))
		hashStr := hash.Sum(nil)
		return string(hashStr), nil
	}
	return "", gerror.New("oceanpayment generate signature err")
}

// NoticePayment TODO 回调
func (o *oOceanPayment) NoticePayment(ctx context.Context, params any) error {
	return nil
}
